home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / pascal / crti.zip / CRTI.PAS
Pascal/Delphi Source File  |  1988-03-03  |  18KB  |  350 lines

  1. UNIT CRTi; {version 1.00 of 03/03/88}
  2.  
  3. {Copyright (c) 1988 by Carley Phillips.  Placed in the PUBLIC DOMAIN.}
  4.  
  5. {
  6. Many of the message threads on Compuserve's BPROGA DL 2 involve the use (and
  7. mis-use) of the CRT unit provided with Turbo 4.  These routines were written
  8. to take some of the mystery out of what CRT routines do and do not do.
  9.  
  10. This unit is an input-only replacement for Borland's CRT.  This means that:
  11. 1. only the input and the misc functions (e.g. Sound) are implemented;
  12. 2. the parts which have to do with screen output are omitted; and
  13. 3. you have access to the source so you can change what you don't like.
  14.  
  15. This allows your programs to avoid USEing CRT at all if your video output
  16. is done with Qwik40, FastWrite, or other packages.  If you use CRTi anywhere,
  17. then make sure none of your units use CRT because the conflicts which may
  18. result may be very difficult to debug.
  19.  
  20. Note that the equivalent of a Turbo variable (which they should have made
  21. public) is contained in HadControlBreak.  This is the variable set by the
  22. control-break handler if CheckBreak is true.  Normally Turbo tests this
  23. during ReadKey and during screen output.  Your program can test this at
  24. any time, however, such as in your replacement screen routines or during
  25. a long mathematical calculation.
  26.  
  27. There are two new public routines here:
  28. 1. a keyboard flushing routine; and
  29. 2. an abort routine you can call if your program finds HadControlBreak true.
  30.  
  31. I will update these routines if anyone notifies me of bugs or of any way in
  32. which these routines do not provide satisfactory duplicates of Borland
  33. functionality.
  34.  
  35. Comments, suggestions, bug reports, etc. should be sent on Compuserve (via
  36. EasyPlex since I'm not necessarily on every few days) to
  37.  
  38. Carley Phillips, 76630,3312.
  39. }
  40.  
  41. {*****************************************************************************}
  42. INTERFACE
  43.  
  44. var
  45.    CheckBreak      : boolean; {false means ignore ^Break}
  46.    SaveInt1B       : pointer; {where old interrupt 1B address is saved}
  47.    HadControlBreak : boolean; {set by ^Break handler if CheckBreak true}
  48.  
  49. procedure Delay (mSec : word);
  50. {
  51. Direct replacement for CRT.Delay.  Delays mSec number of milliseconds.
  52.  
  53. Note that, like Borland's CRT unit, a delay count is determined during
  54. initialization.  This means that if you change your machine speed after
  55. starting a program, the delay values will no longer be what you intended them
  56. to be.
  57. }
  58.  
  59. procedure Sound (Hz : word);
  60. {
  61. Direct replacement for CRT.Sound.  Starts a Hz frequency tone until it is
  62. turned off by NoSound.
  63. }
  64.  
  65. procedure NoSound;
  66. {
  67. Direct replacement for CRT.NoSound.  Stops a tone started with Sound.
  68. }
  69.  
  70. function Keypressed : boolean;
  71. {
  72. Direct replacement for CRT.Keypressed.  If you like, you can also check for
  73. a control break here by un-commenting the indicated lines.
  74. }
  75.  
  76. function ReadKey : char;
  77. {
  78. Direct replacement for CRT.ReadKey.
  79. }
  80.  
  81. procedure FlushKeyboard;
  82. {
  83. NEW public routine to flush the BIOS keyboard buffer.  That is, unless the
  84. user is extraordinarily lucky with his timing of new input, Keypressed will
  85. be false immediatedly following FlushKeyboard.  Normally one flushes the
  86. keyboard buffer in situations such as displaying an error message and then
  87. waiting on the user to press a key.  If the buffer is not flushed, then the
  88. user may have typed ahead enough that the error message will be on the screen
  89. for too short a time to be read.
  90. }
  91.  
  92. procedure ControlBreakAbort;
  93. {
  94. NEW public abort routine called when ReadKey detects that an allowed ^Break has
  95. been entered.  Borland does something similar, but you are free to replace this
  96. with other code or even an external routine.  Alternatively, you can use this
  97. routine from your code if you find that HadControlBreak has become true.
  98. }
  99.  
  100. {*****************************************************************************}
  101. IMPLEMENTATION
  102.  
  103. var
  104.    Cpm : word;   {counts per msec; initialized by InitDelay; used by Delay}
  105.    Scan: byte;   {saves scan code for Keypressed and ReadKey}
  106.    ExitSave : pointer; {place to save old ExitProc}
  107.  
  108. {*****************************************************************************}
  109. procedure Delay (mSec : word);
  110. begin
  111. Inline(                  {Assembly by Inline 03/03/88 22:28}
  112.   $8B/$56/<MSEC/         {         mov    DX,[BP+<mSec];get number of msec}
  113.   $09/$D2/               {         or     DX,DX       ;check it}
  114.   $74/$17/               {         jz     quit        ;quit if 0 delay}
  115.   $BF/>CPM/              {         mov    DI,>Cpm     ;setup addr for subr}
  116.   $8B/$05/               {         mov    AX,[DI]     ;delay count for 1msec}
  117.   $89/$C1/               {onemsec: mov    CX,AX       ;init delay subr counter}
  118.   $E8/$06/$00/           {         call   subr        ;call delay subr}
  119.   $4A/                   {         dec    DX          ;count that we've done 1}
  120.   $75/$F8/               {         jnz    onemsec     ;loop for each msec}
  121.   $E9/$07/$00/           {         jmp    quit        ;skip over subroutine}
  122.   $3A/$05/               {subr:    cmp    AL,[DI]     ;check if constant chngd}
  123.   $75/$02/               {         jnz    out         ;it never will change}
  124.   $E2/$FA/               {         loop   subr        ;count and loop for msec}
  125.   $C3                    {out:     ret                ;return from local subr}
  126.  );                      {quit:                       ;label for end of inline}
  127. end;
  128.  
  129. {*****************************************************************************}
  130. procedure Sound (Hz : word);
  131. begin
  132. Inline(                  {Assembly by Inline 03/03/88 22:28}
  133.   $8B/$4E/<HZ/           {         mov    CX,[BP+<Hz] ;get frequency}
  134.   $B8/$DD/$34/           {         mov    AX,$34DD    ;load lsh of 1,193,181}
  135.   $BA/$12/$00/           {         mov    DX,$0012    ;load msh of 1,193,181}
  136.   $39/$CA/               {         cmp    DX,CX       ;check frequency}
  137.   $73/$1A/               {         jnb    quit        ;quit if too small}
  138.   $F7/$F1/               {         div    CX          ;calculate timer divider}
  139.   $89/$C1/               {         mov    CX,AX       ;save quotient}
  140.   $E4/$61/               {         in     AL,$61      ;get sense data}
  141.   $A8/$03/               {         test   AL,$03      ;check for two lsb}
  142.   $75/$08/               {         jnz    set         ;skip if on}
  143.   $0C/$03/               {         or     AL,$03      ;turn on two lsb}
  144.   $E6/$61/               {         out    $61,AL      ;turn them on}
  145.   $B0/$B6/               {         mov    AL,$B6      ;load control value}
  146.   $E6/$43/               {         out    $43,AL      ;output to timer control}
  147.   $88/$C8/               {set:     mov    AL,CL       ;get lsh of quotient}
  148.   $E6/$42/               {         out    $42,AL      ;output to timer2}
  149.   $88/$E8/               {         mov    AL,CH       ;get msh of quotient}
  150.   $E6/$42                {         out    $42,AL      ;output to timer2}
  151.  );                      {quit:                       ;label for end of inline}
  152. end;
  153.  
  154. {*****************************************************************************}
  155. procedure NoSound;
  156. begin
  157. Inline(                  {Assembly by Inline 03/03/88 22:28}
  158.   $E4/$61/               {         in     AL,$61      ;get sense data}
  159.   $24/$FC/               {         and    AL,$FC      ;turn off two lsb}
  160.   $E6/$61                {         out    $61,AL      ;put it back}
  161.  );                      {quit:                       ;label for end of inline}
  162. end;
  163.  
  164. {*****************************************************************************}
  165. function KeyPressed : boolean;
  166. begin
  167. (*
  168.    if HadControlBreak then   {un-comment this if you want to check ^Break here}
  169.       ControlBreakAbort;
  170. *)
  171. Inline(                  {Assembly by Inline 03/03/88 22:28}
  172.   $80/$3E/>SCAN/$00/     {         cmp    Byte Ptr[>Scan],$00;check scan code}
  173.   $75/$08/               {         jnz    yes         ;not 0 = we saved one}
  174.   $B4/$01/               {         mov    AH,$01      ;check for char}
  175.   $CD/$16/               {         int    $16         ;using BIOS}
  176.   $B0/$00/               {